package com.yuyou.fn.educational.service.impl;

import com.github.wens.framework.service.impl.SuperServiceImpl;
import com.github.wens.mybatisplus.examples.Example;
import com.github.wens.mybatisplus.plugins.Page;
import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.yuyou.fn.common.exception.BusException;
import com.yuyou.fn.common.util.BeanUtils;
import com.yuyou.fn.common.util.CriteriaUtils;
import com.yuyou.fn.common.util.TimeUtils;
import com.yuyou.fn.educational.entity.Discount;
import com.yuyou.fn.educational.entity.DiscountRule;
import com.yuyou.fn.educational.mapper.DiscountMapper;
import com.yuyou.fn.educational.service.IDiscountRuleService;
import com.yuyou.fn.educational.service.IDiscountService;
import com.yuyou.fn.educational.vo.DiscountQueryVo;
import com.yuyou.fn.educational.vo.DiscountSaveOrUpdateVo;
import com.yuyou.fn.platform.permission.DataPermission;
import com.yuyou.fn.platform.service.IAreaTeamService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 *
 * Discount 表数据服务层接口实现类
 *
 */
@Service
public class DiscountServiceImpl extends SuperServiceImpl<DiscountMapper, Discount,Long> implements IDiscountService {


    @Resource
    private IDiscountRuleService discountRuleService ;

    @Resource
    private IAreaTeamService areaTeamService ;





    @Override
    public Page<Discount> findDiscountByQuery(DiscountQueryVo discountQueryVo, DataPermission dataPermission, int pageNo, int pageSize) {
        Example<Discount> example = Discount.createExample();
        Example.Criteria criteria = example.createCriteria();
        CriteriaUtils.fillCondition(criteria,discountQueryVo);
        CriteriaUtils.fillConditionForAreaTeamPermission(criteria,dataPermission.getAreaTeamIds());
        example.orderBy("createTime").desc() ;
        return findPageByExample(example,pageNo,pageSize );
    }

    @CacheEvict(allEntries = true,value = {"CacheOfFindDiscountOfEffectivePolicy","CacheOfFindEffectiveByAreaTeamId","CacheOfFindEffectiveForNetRegByAreaTeamId"})
    @Transactional
    @Override
    public void delDiscount(Long discountId) {
        deleteById(discountId);
    }

    @CacheEvict(allEntries = true,value = {"CacheOfFindDiscountOfEffectivePolicy","CacheOfFindEffectiveByAreaTeamId","CacheOfFindEffectiveForNetRegByAreaTeamId"})
    @Override
    public void saveOrUpdateDiscount(DiscountSaveOrUpdateVo discountSaveOrUpdateVo) {

        if (discountSaveOrUpdateVo.getEffectiveEndTime().getTime()<discountSaveOrUpdateVo.getEffectiveStartTime().getTime()){
            throw new BusException("结束时间必须大于开始时间");
        }

        discountSaveOrUpdateVo.setBusTeamIds(StringUtils.defaultString(discountSaveOrUpdateVo.getBusTeamIds()));
        discountSaveOrUpdateVo.setProductIds(StringUtils.defaultString(discountSaveOrUpdateVo.getProductIds()));
        discountSaveOrUpdateVo.setCourseTemplateIds(StringUtils.defaultString(discountSaveOrUpdateVo.getCourseTemplateIds()));
        discountSaveOrUpdateVo.setGradeIds(StringUtils.defaultString(discountSaveOrUpdateVo.getGradeIds()));
        discountSaveOrUpdateVo.setSubjectIds(StringUtils.defaultString(discountSaveOrUpdateVo.getSubjectIds()));
        discountSaveOrUpdateVo.setPeriodIds(StringUtils.defaultString(discountSaveOrUpdateVo.getPeriodIds()));

        Discount discount = new Discount();

        BeanUtils.copyProperties(discount,discountSaveOrUpdateVo );


        //todo
        if(discount.getDiscountRuleId() != null ){
            DiscountRule discountRule = discountRuleService.findById(discount.getDiscountRuleId());
            discount.setCalFunction(discountRule.getCalFunction());
            discount.setRuleName(discountRule.getName());
            discount.setCategoryId(discountRule.getCategoryId());
            discount.setCategoryName(discountRule.getCategoryName());
            discount.setRemark(discountRule.getRemark());
            discount.setDiscountType(discountRule.getDiscountType());
        }

        if(discount.getAreaTeamId() != null ){
            discount.setAreaTeamName(areaTeamService.findTeamNameById(discount.getAreaTeamId()));
        }

        if(discount.getEffectiveStartTime() == null ){
            discount.setEffectiveStartTime(TimeUtils.now());
        }

        if(discount.getEffectiveEndTime() == null ){
            discount.setEffectiveEndTime(DateUtils.addYears(TimeUtils.now(),1 ));
        }

        discount.setUpdateTime(TimeUtils.now());
        this.checkDiscount(discount);
        if(discount.getDiscountId() == null ){
            discount.setCreateTime(TimeUtils.now());
            insertSelective(discount);
        }else{
            updateSelectiveById(discount);
        }

    }

    private void checkDiscount(Discount discount){
        if (StringUtils.isEmpty(discount.getName())){
            throw new BusException("名称不可为空");
        }
        Example<Discount> example=Discount.createExample();
        example.createCriteria().andEqualTo("name",discount.getName()).andEqualTo("discountRuleId",discount.getDiscountRuleId()).andEqualTo("areaTeamId",discount.getAreaTeamId());
        Discount check=this.findOneByExample(example);
        if (check!=null && !check.getDiscountId().equals(discount.getDiscountId())){
            throw new BusException("该区域下该规则该优惠名称已存在");
        }
    }



    @Cacheable("CacheOfFindDiscountOfEffectivePolicy" )
    @Override
    public List<Discount> findDiscountOfEffectivePolicy(Long areaTeamId) {
        Date now =TimeUtils.now();
        Example<Discount> example = Discount.createExample();
        example.orderBy("name");
        example.createCriteria().andEqualTo("categoryId" ,1 ).andEqualTo("switchStatus" , 1 )
                .andEqualTo("areaTeamId",areaTeamId)
                .andLessThan("effectiveStartTime" , now )
                .andGreaterThan("effectiveEndTime" , now );

        return findListByExample(example);
    }

    @Cacheable("CacheOfFindEffectiveByAreaTeamId")
    @Override
    public List<Discount> findEffectiveWithoutPolicyByAreaTeamId(Long areaTeamId, Date time ) {
        Example<Discount> example = Discount.createExample();
        example.createCriteria().andEqualTo("switchStatus" , 1 )
                .andEqualTo("areaTeamId",areaTeamId)
                .andLessThan("effectiveStartTime" , time )
                .andGreaterThan("effectiveEndTime" , time ).andNotEqualTo("categoryId" , 1 );


        List<Discount> list = findListByExample(example);
        return new ArrayList<>(Collections2.filter(list, new Predicate<Discount>() {
            @Override
            public boolean apply(Discount input) {
                return input.getCategoryId().longValue() == 10  ? false : true;
            }
        }));
    }

    @Cacheable("CacheOfFindEffectiveForNetRegByAreaTeamId")
    @Override
    public List<Discount> findEffectiveForNetRegByAreaTeamId(Long areaTeamId) {
        Date now =TimeUtils.now();
        Example<Discount> example = Discount.createExample();
        example.createCriteria().andIn("categoryId" , Arrays.asList(3,4,10) ).andEqualTo("switchStatus" , 1 )
                .andEqualTo("areaTeamId",areaTeamId)
                .andLessThan("effectiveStartTime" , now )
                .andGreaterThan("effectiveEndTime" , now );

        return findListByExample(example);

    }






}